﻿#region

using System;
using System.Windows.Browser;

#endregion

namespace Radovici.SharedLibrary.Javascript
{
    public static class JavascriptInterop
    {
        static JavascriptInterop()
        {
            if (ThreadHelper.UIContext == null)
                throw new AccessViolationException(
                    "ThreadHelper.UIContext must be initialized before using JavascriptInterop functionality.");
        }

        public static void RegisterScriptableObject(this object obj, string name)
        {
            ThreadHelper.UIContext.Send(delegate { HtmlPage.RegisterScriptableObject(name, obj); }, null);
        }

        public static void Call(string function)
        {
            ThreadHelper.UIContext.Send(Call, function);
        }

        private static void Call(object state)
        {
            var function = state as string;
            if (!string.IsNullOrEmpty(function))
            {
                HtmlPage.Window.Eval(
                    string.Format(
                        @"(function()
{{
    try
    {{
        {0};
    }}
    catch (ex)
    {{
        return ex;
    }}
}})()",
                        function));
            }
        }

        public static object Eval(string function)
        {
            var state = new EvalState {Function = function};
            ThreadHelper.UIContext.Send(Eval, state);
            return state.Output;
        }

        private static void Eval(object state)
        {
            var evalState = (EvalState) state;
            object tmp =
                HtmlPage.Window.Eval(
                    string.Format(
                        @"(function()
{{
    try
    {{
        return {0};
    }}
    catch (ex)
    {{
        return ex;
    }}
}})()",
                        evalState.Function));
            evalState.Output = tmp;
        }

        #region EvalState

        private class EvalState
        {
            public string Function { get; set; }
            public object Output { get; set; }
        }

        #endregion
    }
}